#include <windows.h>
#include "resource.h"

LRESULT WINAPI FlatComboProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	HDC				hdc;
	PAINTSTRUCT		ps;
	RECT			rect;
	RECT			rect2;
	POINT			pt;
	
	WNDPROC			OldComboProc = (WNDPROC)GetWindowLong(hwnd, GWL_USERDATA);

	static BOOL		fMouseDown   = FALSE;
	static BOOL		fButtonDown  = FALSE;
	
	switch(msg)
	{
	case WM_PAINT:
		
		if(wParam == 0)		hdc = BeginPaint(hwnd, &ps);
		else				hdc = (HDC)wParam;

		//
		//	Mask off the borders and draw ComboBox normally
		//
		GetClientRect(hwnd, &rect);

		InflateRect(&rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));

		rect.right -= GetSystemMetrics(SM_CXVSCROLL);

		IntersectClipRect(hdc, rect.left, rect.top, rect.right, rect.bottom);
		
		// Draw the ComboBox
		CallWindowProc(OldComboProc, hwnd, msg, (WPARAM)hdc, lParam);

		//
		//	Now mask off inside and draw the borders
		//
		SelectClipRgn(hdc, NULL);
		rect.right += GetSystemMetrics(SM_CXVSCROLL);

		ExcludeClipRect(hdc, rect.left, rect.top, rect.right, rect.bottom);
		
		// draw borders
		GetClientRect(hwnd, &rect2);
		FillRect(hdc, &rect2, GetSysColorBrush(COLOR_3DSHADOW));

		// now draw the button
		SelectClipRgn(hdc, NULL);
		rect.left = rect.right - GetSystemMetrics(SM_CXVSCROLL);
		
		if(fButtonDown)
			DrawFrameControl(hdc, &rect, DFC_SCROLL, DFCS_SCROLLCOMBOBOX|DFCS_FLAT|DFCS_PUSHED);
			//FillRect(hdc, &rect, GetSysColorBrush(COLOR_3DDKSHADOW));
		else
			DrawFrameControl(hdc, &rect, DFC_SCROLL, DFCS_SCROLLCOMBOBOX|DFCS_FLAT);
			//FillRect(hdc, &rect, GetSysColorBrush(COLOR_3DFACE));

		if(wParam == 0)
			EndPaint(hwnd, &ps);

		return 0;

	// check if mouse is within drop-arrow area, toggle
	// a flag to say if the mouse is up/down. Then invalidate
	// the window so it redraws to show the changes.
	case WM_LBUTTONDBLCLK:
	case WM_LBUTTONDOWN:

		pt.x = (short)LOWORD(lParam);
		pt.y = (short)HIWORD(lParam);

		GetClientRect(hwnd, &rect);

		InflateRect(&rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
		rect.left = rect.right - GetSystemMetrics(SM_CXVSCROLL);

		if(PtInRect(&rect, pt))
		{
			// we *should* call SetCapture, but the ComboBox does it for us
			// SetCapture
			fMouseDown = TRUE;
			fButtonDown = TRUE;
			InvalidateRect(hwnd, 0, 0);
		}

		break;

	// mouse has moved. Check to see if it is in/out of the drop-arrow
	case WM_MOUSEMOVE:

		pt.x = (short)LOWORD(lParam);
		pt.y = (short)HIWORD(lParam);

		if(fMouseDown && (wParam & MK_LBUTTON))
		{
			GetClientRect(hwnd, &rect);

			InflateRect(&rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
			rect.left = rect.right - GetSystemMetrics(SM_CXVSCROLL);

			if(fButtonDown != PtInRect(&rect, pt))
			{
				fButtonDown = PtInRect(&rect, pt);
				InvalidateRect(hwnd, 0, 0);
			}
		}

		break;

	case WM_LBUTTONUP:

		if(fMouseDown)
		{
			// No need to call ReleaseCapture, the ComboBox does it for us
			// ReleaseCapture

			fMouseDown = FALSE;
			fButtonDown = FALSE;
			InvalidateRect(hwnd, 0, 0);
		}

		break;
	}
	
	return CallWindowProc(OldComboProc, hwnd, msg, wParam, lParam);
}

VOID MakeFlatCombo(HWND hwndCombo)
{
	LONG OldComboProc;

	// Remember old window procedure
	OldComboProc = GetWindowLong(hwndCombo, GWL_WNDPROC);
	SetWindowLong(hwndCombo, GWL_USERDATA, OldComboProc);

	// Perform the subclass
	OldComboProc = SetWindowLong(hwndCombo, GWL_WNDPROC, (LONG)FlatComboProc);
}

BOOL CALLBACK DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch(msg)
	{
	case WM_INITDIALOG:
		MakeFlatCombo(GetDlgItem(hwnd, IDC_COMBO1));
		return TRUE;

	case WM_COMMAND:
		switch(LOWORD(wParam))
		{
		case IDOK: case IDCANCEL:
			EndDialog(hwnd, 0);
			return TRUE;
		}
		break;

	case WM_CLOSE:
		EndDialog(hwnd, 0);
		return TRUE;
	}

	return FALSE;
}

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmdLine, int nShowCmd)
{
	DialogBoxParam(0, MAKEINTRESOURCE(IDD_DIALOG1), 0, DlgProc, 0);
	return 0;
}